package com.gitee.l0km.codegen.thrift;

import java.util.List;
import java.util.Map;

import org.apache.commons.cli.Options;
import org.apache.velocity.VelocityContext;

import com.gitee.l0km.codegen.base.AbstractSchema;
import com.gitee.l0km.codegen.base.generator.CodeWriter;
import com.gitee.l0km.codegen.base.generator.Generator;
import com.gitee.l0km.codegen.base.generator.GeneratorConfiguration;
import com.gitee.l0km.codegen.thrift.ThriftServiceDecoratorConfiguration.TaskType;
import com.gitee.l0km.codegen.thrift.metadata.CodegenErpcPointerFilter;
import com.gitee.l0km.codegen.thrift.metadata.CodegenPreAllocFilter;
import com.gitee.l0km.codegen.thrift.metadata.CodegenPreAllocSizeGetter;
import com.gitee.l0km.codegen.thrift.metadata.CodegenRequirednessFilter;
import com.gitee.l0km.codegen.thrift.metadata.ErpcTypePrefixGetter;
import com.gitee.l0km.com4j.cli.Context;
import com.gitee.l0km.javadocreader.ClassCommentProviderFactoryImpl;
import com.gitee.l0km.xthrift.base.metadata.DecoratorThriftEnumMetadata;
import com.gitee.l0km.xthrift.base.metadata.DecoratorThriftFieldMetadata;
import com.gitee.l0km.xthrift.base.metadata.DecoratorThriftStructMetadata;
import com.gitee.l0km.xthrift.base.metadata.Decorators;
import com.gitee.l0km.xthrift.base.metadata.ErpcNameTransformer;
import com.gitee.l0km.xthrift.base.metadata.FieldNameFilters;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;

public class ThriftServiceDecoratorGenerator extends Generator implements ThriftConstants {
	private final ThriftServiceDecoratorOptions options = ThriftServiceDecoratorOptions.getInstance();
	private final ThriftServiceDecoratorConfiguration config = ThriftServiceDecoratorConfiguration.INSTANCE;
	private ThriftSchema thriftSchema;
	public ThriftServiceDecoratorGenerator() {
	}

	@Override
	protected Context createEngineContext() {
		if(!config.getExcludeFields().isEmpty()){
			DecoratorThriftStructMetadata.fieldNameFilters = new FieldNameFilters(config.getExcludeFields());
		}
		Decorators.javadocCommentProviderFactory = new ClassCommentProviderFactoryImpl();
		if(config.getTaskType().equals(TaskType.ERPC_PROXY)){
	        DecoratorThriftEnumMetadata.enumNameTransformer = ErpcNameTransformer.erpcTypeNameTransformer;
	        DecoratorThriftStructMetadata.structNameTransformer = ErpcNameTransformer.erpcTypeNameTransformer;
	        DecoratorThriftFieldMetadata.fieldNameTransformer =  ErpcNameTransformer.erpcFieldNameTransformer;
	        DecoratorThriftFieldMetadata.parameterNameTransformer = ErpcNameTransformer.erpcParemeterNameTransformer;
	        DecoratorThriftFieldMetadata.requirednessFilter = CodegenRequirednessFilter.REQUIREDNESS_FILTER;
	        DecoratorThriftFieldMetadata.typePrefixGetter = ErpcTypePrefixGetter.TYPE_PREFIX_GETTER;
	        DecoratorThriftFieldMetadata.preAllocFilter = CodegenPreAllocFilter.PREALLOC_FILTER;
	        DecoratorThriftFieldMetadata.preAllocsizeGetter = CodegenPreAllocSizeGetter.PREALLOC_SIZE_GETTER;
	        DecoratorThriftFieldMetadata.pointerFilter = CodegenErpcPointerFilter.POINTER_FILTER;
		}
		thriftSchema = new ThriftSchema(config.getInterfaceClasses());
		if(TaskType.ERPC_PROXY.equals(config.getTaskType())){
			thriftSchema.setThriftServiceClasses(config.getThriftServiceClasses()).erpcProxyInit();
		}
		Context context = super.createEngineContext();
		context.setProperty(SCHEMA_INFO, thriftSchema);
		context.setProperty(CXX_HELPER, new CxxHelper());		
		return context;
	}
	
	@Override
	protected GeneratorConfiguration getGeneratorConfiguration() {
		return config;
	}
	@Override
	protected Options getOptions() {
		return options.getOptions();
	}
	@Override
	protected Map<String, List<? extends AbstractSchema>> generateTask() {
		Map<String,List<? extends AbstractSchema>> m = 
				ImmutableMap.<String,List<? extends AbstractSchema>>of(
				DIR_SCHEMA,Lists.<AbstractSchema>newArrayList(),
				DIR_PERSERVICE,thriftSchema.getThriftServiceDecorators(),
				DIR_PERSTRUCT,thriftSchema.getAllStructDecorators()
				);
		return m;
	}

	@Override
	protected void beforeGenerateFile(VelocityContext context, String templateName) {
		AbstractSchema sourceinfo = (AbstractSchema)context.get(SOURCE_INFO);
		if(null !=sourceinfo){
			sourceinfo.backupImportedList();
		}
	}

	@Override
	protected void afterGenerateFile(VelocityContext context, String templateName) {
		AbstractSchema sourceinfo = (AbstractSchema)context.get(SOURCE_INFO);
		if(null !=sourceinfo){
			sourceinfo.restoreImportedList();
		}
	}

	public static void main(String[] args) {
		new ThriftServiceDecoratorGenerator().parseCommandLine(args).initEngine().multiGenerate();
	}

	@Override
	protected CodeWriter getCodeWriter(){
		return config.getCodeWriter();
	}
}
